<?php
/**
 * Created by PhpStorm.
 * User: godjarvis
 * Date: 2020/08/05
 * Time: 16:16
 */

namespace App\Model\Service\DangKou;

use App\Bucket\Session\UserTrait;
use App\Bucket\Utils\MyToolkit;
use App\Http\FeignClient\CommonFeignClient;
use App\Http\Requests\Product\ProductExtraPricePo;
use App\Model\Dao\DangKou\ProductDao;
use App\Model\Dao\DangKou\ProductSizeDao;
use App\Model\Dao\DangKou\PromotionDao;
use App\Model\Dao\DangKou\TaosiFrontPropDao;
use App\Model\Dao\SearchHistoryDao;
use App\Model\Dao\ShareLogDao;
use App\Model\Dao\ShareTimesDao;
use App\Model\Entity\DangKou\Product;
use App\Model\Entity\DangKou\TaosiFrontProps;
use App\Model\Entity\ShareLog;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
use Fresh\Annotation\Autowired;
use Fresh\Annotation\ConnectionField;
use Fresh\Annotation\Transaction;
use Fresh\Mvc\Model\Service;
use Fresh\Mvc\Model\Service\Exception;

class ProductService extends Service
{
    const MOBILE_DANG_KOU_URL = 'http://m.dangkou.net/';

    use UserTrait;

    /**
     * @Autowired()
     * @var ProductDao
     */
    public $productDao;

    /**
     * @Autowired()
     * @var TaosiFrontPropDao
     */
    public $taosiFrontPropDao;

    /**
     * @Autowired()
     * @var ProductSizeDao
     */
    public $productSizeDao;

    /**
     * @Autowired()
     * @var SearchHistoryDao
     */
    public $searchHistoryDao;

    /**
     * @Autowired()
     * @var ShareTimesDao
     */
    public $shareTimesDao;

    /**
     * @Autowired()
     * @var ShareLogDao
     */
    public $shareLogDao;

    /**
     * @Autowired()
     * @var CommonFeignClient
     */
    public $commonFeignClient;

    /**
     * @Autowired()
     * @var PromotionDao
     */
    public $promotionDao;

    /**
     * @ConnectionField(name="dangkou")
     */
    public function list($params, $page, $limit)
    {
        $qb = $this->productDao->getProduct();
        $qb = $this->productDao->setProductConditions($qb, $params);
        $paginator = $this->paginate($qb, $page, $limit);
        foreach ($paginator->items as &$item) {
            $item['name'] = $this->productDao->getItemName($item['pnid']);
        }

        return $paginator;
    }

    public function getFrontProps()
    {
        $propValues = $this->taosiFrontPropDao->getPropValues(TaosiFrontProps::DEFAULT_STYLE_ID);
        foreach ($propValues as &$propValue) {
            $propValue['pid'] = TaosiFrontProps::DEFAULT_STYLE_ID;
        }

        return $propValues;
    }

    public function getInfo($pnid, $pid)
    {
        $products = $this->productDao->getItemProducts($pnid);
        if (empty($products)) {
            $this->error('商品不存在');
        }
        $sizeMap = $this->productSizeDao->getSizes();
        $result = [];
        foreach ($products as $product) {
            $extraPrice = $this->promotionDao->getExtraPrices($product['pid']);
            if ($extraPrice[$product['pid']]) {
                $price_title = $extraPrice[$product['pid']]->price;
                $label = '';
                $activity = '';
                switch ($extraPrice[$product['pid']]->type) {
                    case ProductExtraPricePo::TYPE_SECKILL:
                        $label = '秒杀价';
                        $detail = $this->promotionDao->getSeckill($extraPrice[$product['pid']]->relation_id);
                        $activity = '秒杀活动进行中: ' . date('Y/m/d', $detail['date_start']) . ' - ' . ($detail['date_end'] ? date('Y/m/d', $detail['date_end']) : '售完为止');
                        break;
                    case ProductExtraPricePo::TYPE_SPECIAL:
                        $label = '白菜价';
                        $detail = $this->promotionDao->getSpecial($extraPrice[$product['pid']]->relation_id);
                        $activity = '特价活动进行中: ' . date('Y/m/d', $detail['date_start']) . ' - ' . ($detail['date_end'] ? date('Y/m/d', $detail['date_end']) : '售完为止');
                        break;
                    case ProductExtraPricePo::TYPE_PROMOTION:
                        $label = '促销价';
                        $detail = $this->promotionDao->getPromotion($extraPrice[$product['pid']]->relation_id);
                        $activity = '促销活动(' . $detail['name'] . ')进行中: ' . date('Y/m/d', $detail['date_start']) . ' - ' . ($detail['date_end'] ? date('Y/m/d', $detail['date_end']) : '售完为止');
                        break;
                }
                $price_title_label = $label;
            } else {
                $price_title_label = '会员价';
                // 默认 0.92 折
                $price_title = MyToolkit::convert2float((bcmul($product['price_supply'], 0.92, 2)), 2);
                $activity = '';
            }

            $sizeIds = $this->productSizeDao->getProductSizes($product['pid']);
            $sizeText = $this->parseSizeName($sizeIds, $sizeMap);
            $result[$product['pid']] = [
                'pid'               => $product['pid'],
                'number'            => $product['number'],
                'name'              => $products[0]['name'],
                'color_name'        => $product['color_name'],
                'sizes'             => $sizeText,
                'image'             => $product['image'],
                'price_mark'        => $product['price_mark'],// 市场价(吊牌价)
                'price_min'         => $product['price_min'],// 最低售价(网店售价)
                'price_supply'      => $product['price_supply'],// 普通会员价(供货价), 基准会员价
                'price_title'       => $price_title,// 标签价格
                'price_title_label' => $price_title_label,// 标签
                'activity'          => $activity,// 活动
            ];
        }

        return [
            'pnid'         => $pnid,
            'selected_pid' => $pid,
            'season'       => Product::seasonText()[$products[0]['season']] . '款',
            'fabric'       => $products[0]['fabric'],
            'size_remark'  => $products[0]['size_remark'],
            'description'  => $products[0]['description'],
            'items'        => array_values($result),
            'size_table'   => array_values($this->getSizeTable($pnid))
        ];
    }

    public function history()
    {
        return $this->searchHistoryDao->gets($this->user->id);
    }

    public function parseSizeName(array $sizeIds, array $sizeMap)
    {
        sort($sizeIds);
        $result = [];
        foreach ($sizeIds as $sizeId) {
            if (isset($sizeMap[$sizeId])) {
                $result[] = $sizeMap[$sizeId];
            }
        }

        return implode(',', $result);
    }

    /**
     * 尺码信息表
     * @param $pnid
     * @param bool $showTypeRow 是否逐行返回
     * @return array
     */
    public function getSizeTable($pnid, $showTypeRow = false)
    {
        $types = $this->productSizeDao->getTypes();
        $sizes = $this->productSizeDao->getSizes();
        $format = $this->productSizeDao->getByPid($pnid);
        if (!$format) {
            return [];
        }
        $hasTypes = array_unique(array_column($format, 'type_id'));
        $hasSizes = array_filter(array_unique(array_column($format, 'size_id')));

        // 处理尺码信息数据
        foreach ($format as $item) {
            if ($showTypeRow) {
                $tmp[$item['size_id']][$item['type_id']] = $item['format'];
            } else {
                $tmp[$item['type_id']][$item['size_id']] = $item['format'];
            }
        }

        $data = [];
        if ($showTypeRow) {
            $i = 1;
            $hasTitle = false;
            foreach ($hasSizes as $sizeId) {
                if (!$hasTitle) {
                    $data[0][] = '尺寸';
                }
                $data[$i][] = $sizes[$sizeId];
                foreach ($hasTypes as $typeId) {
                    if (!$hasTitle) {
                        $data[0][] = $types[$typeId];
                    }
                    $data[$i][] = $tmp[$sizeId][$typeId] ?? '';
                }
                $i++;
                $hasTitle = true;
            }
        } else {
            $data = $hasSizes ? [[0 => '尺码']] : [];
            foreach ($hasSizes as $sizeId) {
                $data[0][] = $sizes[$sizeId];
            }
            $i = 1;
            foreach ($hasTypes as $typeId) {
                $data[$i][] = $types[$typeId];
                $hasValue = true;
                foreach ($hasSizes as $sizeId) {
                    $value = $tmp[$typeId][$sizeId] ?? '';
                    $hasValue = $hasValue && $value;
                    $data[$i][] = $value;
                }
                // 过滤无值的列
                if ($hasValue === false) {
                    unset($data[$i]);
                }
                $i++;
            }
        }

        return $data;
    }

    /**
     * @param string $ids
     * @return bool
     * @throws Exception
     */
    public function flush(string $ids)
    {
        $log_ids = explode(',', $ids);
        if ($log_ids) {
            try {
                return $this->searchHistoryDao->delete($this->user->id, $log_ids) > 0;
            } catch (\Exception $e) {
                throw new Exception('删除失败');
            }
        }

        $this->error('请选择删除项');
    }

    /**
     * @Transaction()
     */
    public function share(?string $pnid, ?string $pid, string $type, string $location)
    {
        $dev_id = $this->user->id;
        $row = [];
        switch ($location) {
            case ShareLog::LOCATION_PRODUCT_INFO:
                if ($pnid && $pid) {
                    $row = [
                        'pnid' => $pnid,
                        'pid'  => $pid
                    ];
                }
                break;
            case ShareLog::LOCATION_USER_CENTER:
                $row = [
                    'pnid' => 0,
                    'pid'  => 0
                ];
                break;
        }

        if (empty($row)) {
            $this->error('分享参数不匹配');
        }

        $this->shareLogDao->insert(array_merge([
            'dev_id'   => $dev_id,
            'type'     => $type,
            'location' => $location,
        ], $row));

        $month_share = $this->shareTimesDao->getByType($dev_id, date('Y-m'), $type);

        if ($month_share) {
            $this->shareTimesDao->update([
                'times' => $month_share['times'] + 1
            ], $dev_id, $month_share['month'], $type);
        } else {
            $this->shareTimesDao->insert([
                'dev_id' => $dev_id,
                'times'  => 1,
                'type'   => $type,
                'month'  => date('Y-m'),
            ]);
        }

        return true;
    }

    public function getQRCode(int $pnid, int $pid)
    {

        $productInfo = $this->productDao->getProductInfo($pnid, $pid);

        if (!$productInfo) {
            $this->error('产品不存在');
        }

        $data = $this->getCodeData();

        //上传生成图片 url
        $imageInfo = $this->commonFeignClient->uploadImageBase64($data, 'qrcode.png');

        return [
            'image_url' => $productInfo['image'],
            'code_url'  => $imageInfo['url'],
            'name'      => $productInfo['name'],
            'price'     => $productInfo['price'],
        ];
    }

    public function getCodeData()
    {
        $qrCode = new QrCode();

        //设置二维码上的内容
        $qrCode->setText(self::MOBILE_DANG_KOU_URL);

        //二维码尺寸
        $qrCode->setSize(300);

        //设置输出的二维码图片格式
        $qrCode->setWriterByName('png');

        $qrCode->setMargin(10);

        $qrCode->setEncoding('UTF-8');

        //设置二维码的纠错率，可以有 low、medium、quartile、hign 多个纠错率
        $qrCode->setErrorCorrectionLevel(ErrorCorrectionLevel::HIGH());

        //设置二维码的 rgb 颜色和透明度 a，这里是黑色
        $qrCode->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0]);

        //设置二维码图片的背景底色，这里是白色
        $qrCode->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);

        return $qrCode->writeDataUri();
    }

    public function preview(string $type, ?string $pnid, ?string $pid)
    {
        $url = self::MOBILE_DANG_KOU_URL;
        switch ($type) {
            // 商品详情页分享
            case 1:
                if ($pnid && $pid) {
                    $url = sprintf('%sproduct/info/%s.html#%s', self::MOBILE_DANG_KOU_URL, $pnid, $pid);
                }
                break;
            // 个人中心页分享
            case 2:
                $url = self::MOBILE_DANG_KOU_URL;
                break;
        }

        return compact('url');
    }
}
